package com.atguigu.gulimall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 异步编排测试
 *
 * @author LaiSanShan
 * @date 2021-08-16
 */
public class CompletableFutureTest {
    private static ExecutorService threadPool = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main。。。开始" + Thread.currentThread().getId());
//        runAsyncTest();
//        supplyAsyncTest();
        // 异常时，发现不能跟上面一样用函数去生成线程执行；因为函数那种是拆开的，不是链式调用
//        supplyAsyncThenTest();
        // 链式调用就可以
        supplyAsyncThenTest2();
        System.out.println("main。。。结束");
    }

    /**
     * 不带返回值
     */
    private static void runAsyncTest() {
        CompletableFuture.runAsync(() -> {
            System.out.println("CompletableFuture不带返回值：子线程执行。。。" + Thread.currentThread().getId());
        }, threadPool);
    }

    /**
     * 带返回值
     */
    private static void supplyAsyncTest() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("CompletableFuture带返回值：子线程执行。。。" + Thread.currentThread().getId());
            return 1;
        }, threadPool);
        Integer res = completableFuture.get();
        System.out.println(res);
    }

    /**
     * 带返回值，可进行异步编排：非链式调用
     * 对异常没处理，影响到main线程
     */
    private static void supplyAsyncThenTest() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("CompletableFuture异步编排：子线程执行。。。" + Thread.currentThread().getId());
            int i = 1 / 0;
            return 1;
        }, threadPool);
        System.out.println("CompletableFuture异步编排-第一个线程运行结果：" + completableFuture.get());
        CompletableFuture<Integer> completableFuture1 = completableFuture.whenComplete((res, exception) -> {
            System.out.println("CompletableFuture异步编排-同一个线程" + Thread.currentThread().getId() + "继续运行，结果：" + res + "，异常：" + exception);
        });
        System.out.println("CompletableFuture异步编排-第一个线程运行结果：" + completableFuture1.get());
        CompletableFuture<Integer> exceptionally = completableFuture.exceptionally(throwable -> {
            System.out.println("CompletableFuture异步编排-第一个线程" + Thread.currentThread().getId() + "运行异常：" + throwable);
            return 10;
        });
    }

    /**
     * 带返回值，可进行异步编排：链式调用
     * supplyAsync是开了其他线程运行，其他操作都是在main线程里运行
     */
    private static void supplyAsyncThenTest2() throws ExecutionException, InterruptedException {
        /**
         CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
         System.out.println("CompletableFuture异步编排：子线程执行。。。" + Thread.currentThread().getId());
         int i = 1 / 0;
         return 1;
         }, threadPool).whenComplete((res, exception) -> {
         System.out.println("CompletableFuture异步编排-同一个线程继续运行" + Thread.currentThread().getId() + "，结果：" + res + "，异常：" + exception);
         }).exceptionally(throwable -> {
         System.out.println("CompletableFuture异步编排-第一个线程" + Thread.currentThread().getId() + "运行异常：" + throwable);
         // 修改返回值
         return 10;
         });
         Integer res = completableFuture.get();
         System.out.println("最终结果res：" + res);
         */
        // 区别whenComplete的handler对结果进行处理
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("CompletableFuture异步编排：子线程执行。。。" + Thread.currentThread().getId());
            int i = 1 / 0;
            return 1;
        }, threadPool).handle((res, exception) -> {
            System.out.println("CompletableFuture异步编排-同一个线程继续运行" + Thread.currentThread().getId() + "，结果：" + res + "，异常：" + exception);
            return 10;
        });
        Integer res = completableFuture.get();
        System.out.println(res);

    }

}
